﻿using Microsoft.Win32;
using NLog;
using playwrightJu3.Controls;
using playwrightJu3.Core;
using playwrightJu3.Properties;
using playwrightJu3.Windows;
using System;
using System.Diagnostics;
using System.Drawing.Text;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;

namespace playwrightJu3
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Project currentProject = null;

        private static Logger logger = LogManager.GetCurrentClassLogger();
        public MainWindow()
        {
            InitializeComponent();
            mainEdit.IsDocumentEnabled = true;
            mainEdit.Document = new FlowDocument();
            CheckProjectAndFileStatus();
            isTextChanged = false;
        }

        private string GetStringFromResources(string key)
        {
            return Properties.Resources.ResourceManager.GetString(key) ?? key;
        }

        private bool isTextChanged = false;
        private void AddTip_Click(object sender, RoutedEventArgs e)
        {
            // 获取当前光标位置
            TextPointer caret = mainEdit.CaretPosition;

            // 创建按钮
            var inlineButton = new Tip() { Content = GetStringFromResources("NewTip") };

            // 插入行内控件
            InlineUIContainer container = new InlineUIContainer(inlineButton, caret);

            // 将光标移到按钮后面
            mainEdit.CaretPosition = container.ElementEnd;
        }

        private void ToggleButton_Checked(object sender, RoutedEventArgs e)
        {
            if (mainEdit?.Document?.Blocks != null)
            {
                foreach (Block block in mainEdit.Document.Blocks)
                {
                    if (block is Paragraph paragraph)
                    {
                        foreach (Inline inline in paragraph.Inlines)
                        {
                            if (inline is InlineUIContainer container && container.Child is Tip tip)
                            {
                                tip.Visibility = Visibility.Visible;
                            }
                        }
                    }
                }
            }
        }

        private void ToggleButton_Unchecked(object sender, RoutedEventArgs e)
        {
            if (mainEdit?.Document?.Blocks != null)
            {
                foreach (Block block in mainEdit.Document.Blocks)
                {
                    if (block is Paragraph paragraph)
                    {
                        foreach (Inline inline in paragraph.Inlines)
                        {
                            if (inline is InlineUIContainer container && container.Child is Tip tip)
                            {
                                tip.Visibility = Visibility.Collapsed;
                            }
                        }
                    }
                }
            }
        }

        private void NewProj_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new NewProjDialog();
            if (dialog.ShowDialog() == true)
            {
                Project project = new Project()
                {
                    Location = dialog.projLocationTextBox.Text,
                    Title = dialog.projTitleTextBox.Text
                };
                currentProject = project;
                currentProject.ProjectInitialized += () => { OpenProject(currentProject); };
                project.Open();
                mainTab.SelectedIndex = 0;
            }
        }

        private void About_Click(object sender, RoutedEventArgs e)
        {
            AboutDialog dialog = new AboutDialog();
            dialog.ShowDialog();
        }

        private void OpenProject_Click(object sender, RoutedEventArgs e)
        {

            OpenFolderDialog dialog = new OpenFolderDialog()
            {
                Multiselect = false,
                Title = GetStringFromResources("SelectYourProjectFolder"),
            };
            if (dialog.ShowDialog() == true)
            {
                string selectedFolder = dialog.FolderName;
                string parentFolder = Directory.GetParent(selectedFolder)?.FullName;

                Project project = new Project()
                {
                    Location = parentFolder,
                    Title = Path.GetFileName(dialog.SafeFolderName)
                };
                currentProject = project;
                currentProject.ProjectInitialized += () => { OpenProject(currentProject); };
                project.Open();
                mainTab.SelectedIndex = 0;
            }
        }

        private void mainTab_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (isTextChanged)
            {
                YesNoCancelDialog dialog = new YesNoCancelDialog();
                dialog.Title = GetStringFromResources("UnsavedChanges");
                dialog.infoTextBlock.Text = GetStringFromResources("UnsavedChangesOnChangingTabDescription");
                dialog.ShowDialog();
                if (dialog.Result == YesNoCancelDialog.ResultType.Yes)
                {
                    //mainTab.SelectedItem = currentTabItem;
                    SaveFile_Click(sender, new RoutedEventArgs());
                }
                else if (dialog.Result == YesNoCancelDialog.ResultType.No)
                {
                    // 不保存，直接切换标签页
                }
                else if (dialog.Result == YesNoCancelDialog.ResultType.Cancel)
                {
                    //事件解绑重绑，防止重新调用
                    mainTab.SelectionChanged -= mainTab_SelectionChanged;
                    mainTab.SelectedItem = currentTabItem;
                    mainTab.SelectionChanged += mainTab_SelectionChanged;
                    return;
                }
            }
            if (mainTab.Items.Count != 0)
            {
                TabItem selectedItem = mainTab.SelectedItem as TabItem;
                string filePath = Path.Combine(currentProject.Location, currentProject.Title, selectedItem.Header.ToString());
                ReadFile(filePath);
            }

        }

        private void Window_GotFocus(object sender, RoutedEventArgs e)
        {
            CheckProjectAndFileStatus();
        }

        private void CheckProjectAndFileStatus()
        {
            //没有打开项目时，禁用新建文件按钮
            if (currentProject == null)
            {
                newFileMenu.IsEnabled = false;
                saveFileMenu.IsEnabled = false;
                mainEdit.IsEnabled = false;
            }
            else
            {
                newFileMenu.IsEnabled = true;
                //没有Tab时，禁用保存按钮
                if (mainTab.Items.Count == 0)
                {
                    saveFileMenu.IsEnabled = false;
                    mainEdit.IsEnabled = false;
                }
                else
                {
                    saveFileMenu.IsEnabled = true;
                    mainEdit.IsEnabled = true;
                }
            }
            currentTabItem = (TabItem)mainTab.SelectedItem;
        }

        private void OpenProject(Project project)
        {
            mainTab.Items.Clear();
            mainEdit.Document = new FlowDocument();
            Title = $"{project.Title} - playwrightJu";
            foreach (var item in project.Files)
            {
                if (!Checkers.IsValidJuFile(Path.Combine(project.Location, project.Title, item)))
                {
                    InfoDialog dialog = new InfoDialog(GetStringFromResources("NotAProjectFolder"), GetStringFromResources("NotAProjectFolderDescription"));
                    dialog.ShowDialog();
                    currentProject = null;
                    mainTab.Items.Clear();
                    return;
                }

                var tabItem = new TabItem
                {
                    Header = item
                };
                isTextChanged = false;
                mainTab.Items.Add(tabItem);
                mainTab.SelectedItem = tabItem;
                string filePath = Path.Combine(currentProject.Location, currentProject.Title, item);
                ReadFile(filePath);
            }
            CheckProjectAndFileStatus();

        }

        private void Exit_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (currentProject != null && mainTab.Items.Count != 0)
            {
                if (isTextChanged)
                {
                    YesNoCancelDialog dialog = new YesNoCancelDialog();
                    dialog.Title = GetStringFromResources("UnsavedChanges");
                    dialog.infoTextBlock.Text = GetStringFromResources("UnsavedChangesOnClosingDescription");
                    dialog.ShowDialog();
                    if (dialog.Result == YesNoCancelDialog.ResultType.Yes)
                    {
                        SaveFile_Click(sender, new RoutedEventArgs());
                    }
                    else if (dialog.Result == YesNoCancelDialog.ResultType.No)
                    {
                        // 不保存，直接关闭
                    }
                    else if (dialog.Result == YesNoCancelDialog.ResultType.Cancel)
                    {
                        e.Cancel = true; // 取消关闭窗口
                    }

                }
            }

        }

        private void ReadFile(string filePath)
        {
            if (System.IO.File.Exists(filePath))
            {
                Core.File file = new Core.File(currentProject) { Name = Path.GetFileName(filePath) };
                mainEdit.Document = file.Read();
                TextRange textRange = new TextRange(mainEdit.Document.ContentStart, mainEdit.Document.ContentEnd);
                mainEdit.CaretPosition = textRange.End; // 将光标移动到文档末尾
                isTextChanged = false;
            }
            else
            {
                mainEdit.Document = new FlowDocument();
            }
            CheckProjectAndFileStatus();
        }

        private void SaveFile_Click(object sender, RoutedEventArgs e)
        {
            isTextChanged = false;
            TextRange textRange = new TextRange(mainEdit.Document.ContentStart, mainEdit.Document.ContentEnd);
            TabItem selectedItem = currentTabItem;
            Core.File file = new Core.File(currentProject) { Name = selectedItem.Header.ToString() };
            file.Save(textRange);
            //currentProject.Open(); //取消掉这一行以修复重新打开项目产生的副作用。暂不明确取消之后可能带来的副作用。
        }

        private void NewFile_Click(object sender, RoutedEventArgs e)
        {
            NewFileDialog dialog = new NewFileDialog(currentProject);
            if (dialog.ShowDialog() == true)
            {
                foreach (TabItem item in mainTab.Items)
                {
                    if (item.Header.ToString() == dialog.fileNameTextBox.Text)
                    {
                        mainTab.SelectedItem = item;
                    }
                }
            }
            CheckProjectAndFileStatus();

        }

        private void Undo_Click(object sender, RoutedEventArgs e)
        {
            mainEdit.Undo();
        }

        private void Redo_Click(object sender, RoutedEventArgs e)
        {
            mainEdit.Redo();
        }

        private void AddTipCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            AddTip_Click(sender, e);
        }

        private void NewProjectCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            NewProj_Click(sender, e);
        }

        private void NewFileCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            NewFile_Click(sender, e);
        }

        private void SaveFileCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            SaveFile_Click(sender, e);
        }

        private void OpenProjectCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            OpenProject_Click(sender, e);
        }

        private void ToggleTipVisibilityCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            ToggleTipVisibilityButton.IsChecked = !ToggleTipVisibilityButton.IsChecked;
        }

        private void SaveFileCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (saveFileMenu.IsEnabled)
            {
                e.CanExecute = true;
            }
            else
            {
                e.CanExecute = false;
            }
        }

        private void NewFileCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (newFileMenu.IsEnabled)
            {
                e.CanExecute = true;
            }
            else
            {
                e.CanExecute = false;
            }
        }

        private void mainEdit_TextChanged(object sender, TextChangedEventArgs e)
        {
            isTextChanged = true;
        }

        private FlowDocument currentDocument = new FlowDocument();
        private TabItem currentTabItem = new TabItem();
        private void mainTab_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            currentDocument = mainEdit.Document;
            currentTabItem = mainTab.SelectedItem as TabItem ?? new TabItem();
        }

        private void mainTab_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            currentDocument = mainEdit.Document;
            currentTabItem = mainTab.SelectedItem as TabItem ?? new TabItem();
        }

        private void ToggleBold_Checked(object sender, RoutedEventArgs e)
        {
            mainEdit.Selection.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
        }

        private void ToggleBold_Unchecked(object sender, RoutedEventArgs e)
        {
            mainEdit.Selection.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Normal);
        }

        private void ToggleItalic_Checked(object sender, RoutedEventArgs e)
        {
            mainEdit.Selection.ApplyPropertyValue(TextElement.FontStyleProperty, FontStyles.Italic);
        }

        private void ToggleItalic_Unchecked(object sender, RoutedEventArgs e)
        {
            mainEdit.Selection.ApplyPropertyValue(TextElement.FontStyleProperty, FontStyles.Normal);

        }

        private void ToggleUnderline_Checked(object sender, RoutedEventArgs e)
        {
            mainEdit.Selection.ApplyPropertyValue(Inline.TextDecorationsProperty, TextDecorations.Underline);
        }
        private void ToggleUnderline_Unchecked(object sender, RoutedEventArgs e)
        {
            mainEdit.Selection.ApplyPropertyValue(Inline.TextDecorationsProperty, null);
        }
        private void mainEdit_SelectionChanged(object sender, RoutedEventArgs e)
        {
            if (mainEdit.Selection.GetPropertyValue(TextElement.FontWeightProperty) as FontWeight? == FontWeights.Bold)
            {
                ToggleBold.IsChecked = true;
            }
            else
            {
                ToggleBold.IsChecked = false;
            }
            if (mainEdit.Selection.GetPropertyValue(TextElement.FontStyleProperty) as FontStyle? == FontStyles.Italic)
            {
                ToggleItalic.IsChecked = true;
            }
            else
            {
                ToggleItalic.IsChecked = false;
            }
            if (mainEdit.Selection.GetPropertyValue(Inline.TextDecorationsProperty) == TextDecorations.Underline)
            {
                ToggleUnderline.IsChecked = true;
            }
            else
            {
                ToggleUnderline.IsChecked = false;
            }
            FontFamily? font = mainEdit.Selection.GetPropertyValue(TextElement.FontFamilyProperty) as FontFamily;
            FontFamilyCombo.SelectedItem = font?.Source;
            try
            {
                double fontSize = Convert.ToDouble(mainEdit.Selection.GetPropertyValue(TextElement.FontSizeProperty));
                FontSizeCombo.Text = fontSize.ToString();
            }
            catch (Exception ex)
            {
                logger.Warn(ex, "Failed to get font size from selection.");
            }

        }

        private void Cut_Click(object sender, RoutedEventArgs e)
        {
            mainEdit.Cut();
        }

        private void Copy_Click(object sender, RoutedEventArgs e)
        {
            mainEdit.Copy();
        }

        private void Paste_Click(object sender, RoutedEventArgs e)
        {
            mainEdit.Paste();
        }

        private void ViewHelp_Click(object sender, RoutedEventArgs e)
        {
            Process.Start("explorer.exe", "https://zhchmmx.github.io/playwrightju/help.html");
        }

        private void ViewHelpCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Process.Start("explorer.exe", "https://zhchmmx.github.io/playwrightju/help.html");
        }

        private void ViewHelpCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = false;//TODO: 在帮助页面未搭建好时，保持false
        }

        private void FontFamilyCombo_DropDownClosed(object sender, EventArgs e)
        {
            try
            {
                FontFamily font = new FontFamily(FontFamilyCombo.SelectedItem.ToString());
                mainEdit.Selection.ApplyPropertyValue(TextElement.FontFamilyProperty, font);
            }
            catch (NullReferenceException)
            {

            }

        }

        private void Window_Initialized(object sender, EventArgs e)
        {
            InstalledFontCollection fonts = new InstalledFontCollection();
            foreach (var font in fonts.Families)
            {
                FontFamilyCombo.Items.Add(font.Name);
            }
            FontFamilyCombo.SelectedItem = "Microsoft YaHei";
        }

        private void FontSizeCombo_DropDownClosed(object sender, EventArgs e)
        {
            try
            {
                mainEdit.Selection.ApplyPropertyValue(TextElement.FontSizeProperty, Convert.ToDouble(FontSizeCombo.Text));
            }
            catch (NullReferenceException)
            {
                InfoDialog infoDialog = new InfoDialog(GetStringFromResources("InvalidFontSize"), GetStringFromResources("InvalidFontSizeDescription"));
                infoDialog.ShowDialog();
            }
            catch (FormatException)
            {
                InfoDialog infoDialog = new InfoDialog(GetStringFromResources("InvalidFontSize"), GetStringFromResources("InvalidFontSizeDescription"));
                infoDialog.ShowDialog();
            }

        }

        private void FontSettingsMenu_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.FontDialog fontDialog = new System.Windows.Forms.FontDialog();
            if (fontDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                System.Drawing.Font font = fontDialog.Font;
                FontFamily fontFamily = new FontFamily(font.Name);
                double fontSize = font.SizeInPoints;
                FontStyle fontStyle = font.Italic ? FontStyles.Italic : FontStyles.Normal;
                FontWeight fontWeight = font.Bold ? FontWeights.Bold : FontWeights.Normal;
                TextDecorationCollection textDecorations = new TextDecorationCollection();

                if (font.Strikeout && font.Underline)
                {
                    textDecorations.Add(TextDecorations.Underline[0]);
                    textDecorations.Add(TextDecorations.Strikethrough[0]);

                }
                else if (font.Underline == true && font.Strikeout == false)
                {
                    textDecorations.Add(TextDecorations.Underline[0]);
                }
                else if (font.Underline == false && font.Strikeout == true)
                {
                    textDecorations.Add(TextDecorations.Strikethrough[0]);
                }
                else if (font.Underline == false && font.Strikeout == false)
                {
                    mainEdit.Selection.ApplyPropertyValue(Inline.TextDecorationsProperty, null);
                }

                mainEdit.Selection.ApplyPropertyValue(TextElement.FontFamilyProperty, fontFamily);
                mainEdit.Selection.ApplyPropertyValue(TextElement.FontSizeProperty, fontSize);
                mainEdit.Selection.ApplyPropertyValue(TextElement.FontStyleProperty, fontStyle);
                mainEdit.Selection.ApplyPropertyValue(TextElement.FontWeightProperty, fontWeight);
                mainEdit.Selection.ApplyPropertyValue(Inline.TextDecorationsProperty, textDecorations);
            }
        }

        private void FontSizeCombo_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                FontSizeCombo_DropDownClosed(sender, e);
            }
        }
    }
}
